﻿#include "Utils.h"
#include "BlockNoRepeatList.h"
#include "PriorityThread.h"

#include <QEvent>
#include <QImage>
#include <QDebug>
#include <math.h>

BEGIN_NAMESPACE_CIQTEK

#define BATCH_SYNC_MSEC			50

CiqTime::CiqTime() 
    : QTime()
    , m_isStart(false)
{
}

CiqTime::~CiqTime()
{
}

bool CiqTime::isGreaterThan(const uint32_t time)
{
    if (m_isStart && this->elapsed() >= time)
    {
        return true;
    }

    return false;
}

bool CiqTime::isStart()
{
	return m_isStart;
}

void CiqTime::restart()
{
    m_isStart = true;
    QTime::restart();
}

void CiqTime::start()
{
    m_isStart = true;
    QTime::start();
}

void CiqTime::stop()
{
    m_isStart = false;
}

//////////////////////////////////////////////////////////////////////////

CiqSettings::CiqSettings(QObject *parent /*= nullptr*/)
    : QSettings(parent)
{
	init();
}

CiqSettings::CiqSettings(QSettings::Scope scope, QObject *parent /*= nullptr*/)
    : QSettings(scope, parent)
{
	init();
}

CiqSettings::CiqSettings(const QString & fileName, QSettings::Format format, QObject * parent /*= nullptr*/)
    : QSettings(fileName, format, parent)
{
	init();
}

CiqSettings::CiqSettings(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application /*= QString()*/, QObject *parent /*= nullptr*/)
    : QSettings(format, scope, organization, application, parent)
{
	init();
}

CiqSettings::CiqSettings(QSettings::Scope scope, const QString & organization, const QString & application /*= QString()*/, QObject * parent /*= nullptr*/)
    : QSettings(scope, organization, application, parent)
{
	init();
}

CiqSettings::CiqSettings(const QString & organization, const QString & application, QObject * parent /*= nullptr*/)
    : QSettings(organization, application, parent)
{
	init();
}

CiqSettings::~CiqSettings()
{
    // 停线程
    m_stopFlag = true;
    m_workerThread->stop();

    // 将指令队列同步消费完
    while (true)
    {
        CmdItemData itemData;
        bool ret = m_noRepeatList->pop(itemData);

        if (ret)
        {
            if (itemData.isForce || !QSettings::contains(itemData.key))
            {
                QSettings::setValue(itemData.key, itemData.value);
            }
        }
        else
        {
            break;
        }
    }

    // 最后同步
    QSettings::sync();

    // 清空指令队列
    m_noRepeatList->clear();
    if (m_noRepeatList)
    {
        delete m_noRepeatList;
        m_noRepeatList = NULL;
    }
}

void CiqSettings::setValue(const QString & key, const QVariant & value, const bool isForce)
{
    if (isForce || !QSettings::contains(key))
    {
        QSettings::setValue(key, value);
    }
}

void CiqSettings::setValue(const QString & group, const QString & key, const QVariant & value, const bool isForce)
{
    QString fullName = QString("%1/%2").arg(group).arg(key);
	setValue(fullName, value, isForce);
}

void CiqSettings::setValueAsync(const QString& key, const QVariant& value, const bool isForce /*= true*/)
{
    CmdItemData itemData;
    itemData.key = key;
    itemData.value = value;
    itemData.isForce = isForce;

    m_noRepeatList->push(key, itemData);
}

void CiqSettings::setValueAsync(const QString& group, const QString& key, const QVariant& value, const bool isForce /*= true*/)
{
    QString fullName = QString("%1/%2").arg(group).arg(key);
    setValueAsync(fullName, value, isForce);
}

void CiqSettings::init()
{
    m_noRepeatList = new BlockNoRepeatList<QString, CmdItemData>();
    m_noRepeatList->setBlock(false);

    m_stopFlag = false;
    m_workerThread = new PriorityThread(this, std::bind(&CiqSettings::run, this));
    m_workerThread->start(QThread::LowPriority);
}

void CiqSettings::run()
{
    QTime time;
    time.restart();

    while (!m_stopFlag)
    {
        if (time.elapsed() >= BATCH_SYNC_MSEC)
        {
            QSettings::sync();
            time.restart();
        }

        CmdItemData itemData;
        bool ret = m_noRepeatList->pop(itemData);

        if (ret)
        {
            if (itemData.isForce || !QSettings::contains(itemData.key))
            {
                QSettings::setValue(itemData.key, itemData.value);
            }
        }
        else
        {
            QThread::msleep(5);
        }
    }
}

bool CiqSettings::event(QEvent * event)
{
    if (event->type() == QEvent::UpdateRequest)
    {
        event->accept();
        return true;
    }

    return QSettings::event(event);
}

END_NAMESPACE_CIQTEK
